using System;
using System.Collections.Generic;
using System.Text;

namespace GuavaData
{
    public class Except : Operator
    {
        // Relational algebra except operator: child1 - child2

        #region Fields
        Operator child1;
        public Operator Child1
        {
            get { return child1; }
            set { child1 = value; }
        }

        Operator child2;
        public Operator Child2
        {
            get { return child2; }
            set { child2 = value; }
        }

        public string alias;
        #endregion Fields

        public Except(Operator child1, Operator child2)
        {
            // Dummy check
            if (child1.exposedColumns.Count != child2.exposedColumns.Count)
            {
                throw new Exception("Column count does not match for Except operator.");
            }
            
            this.child1 = child1;
            this.child2 = child2;
            child1.parent = this;
            child2.parent = this;

            // Create the output schema, and validate that the arguments are union compatible
            this.exposedColumns = new List<string>();
            this.exposedDomains = new List<GuavaData.Domain.Domain>();

            for (int i = 0; i < child1.exposedColumns.Count; i++)
            {
                this.exposedColumns.Add(child1.exposedColumns[i]);
                if ( child1.exposedColumns.Count != child2.exposedColumns.Count) //!(child1.exposedDomains[i].Equals(child2.exposedDomains[i])))
                {
                    throw new Exception("Column count does not match for Except operator.");
                }
                this.exposedDomains.Add(child1.exposedDomains[i]);
            }
        }

        public Except(Operator child1, Operator child2, string alias)
            : this(child1, child2)
        {
            this.alias = alias;
        }

        public override SqlText Visit(Provider qv)
        {
            return qv.Transform(this);
        }
        public override void Visit(Transform t, Command c)
        {
            t.Expand(this, c);
        }

        public override Operator Clone()
        {
            return new Except(child1.Clone(), child2.Clone());
        }

        public override void NotifyChange(Operator old, Operator newOp)
        {
            if (this.child1 == old)
            {
                this.child1 = newOp;
                newOp.parent = this;
            }
            if (this.child2 == old)
            {
                this.child2 = newOp;
                newOp.parent = this;
            }
        }

        public override void Visit(Channel c, string table)
        {
            c.MapAliases(this, table);
        }

    }
}
